package com.lagou.handler;

import com.lagou.service.RpcRequest;
import com.lagou.service.UserServiceImpl;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.concurrent.EventExecutorGroup;
import org.springframework.beans.BeansException;
import org.springframework.cglib.reflect.FastClass;
import org.springframework.cglib.reflect.FastMethod;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;

/**
 * 自定义业务处理器
 */
@Component
public class UserServerHandler extends ChannelInboundHandlerAdapter implements ApplicationContextAware {


    private static ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        UserServerHandler.applicationContext=applicationContext;
    }

    //当客户端读数据时 该方法会被调用
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //当客户端发送请求时会传递一个参数 UserService#sayHello#are you ok

        //判断当前的请求是否符合规则
        /*if(msg.toString().startsWith("UserService")){
            //2，如果符合规则调用实现类 获得一个result
            UserServiceImpl userService=new UserServiceImpl();
            String result = userService.sayHello(msg.toString().substring(msg.toString().lastIndexOf("#") + 1));
            //3,把调用实现类获取的结果写回客户端
            ctx.writeAndFlush(result);
        }*/
        RpcRequest msg1=(RpcRequest)msg;
        Object handler=handler(msg1);
        ctx.writeAndFlush("success");
        //ctx.writeAndFlush(handler);

    }


    /**
     * 通过反射执行目标方法
     * @param request
     * @return
     * @throws ClassNotFoundException
     * @throws InvocationTargetException
     */
    private Object handler(RpcRequest request) throws ClassNotFoundException, InvocationTargetException {
        //使用class.forName进行加载Class文件
        Class<?> aClass = Class.forName(request.getClassName());
        Object serviceBean = applicationContext.getBean(aClass);
        Class<?> serviceClass = serviceBean.getClass();
        String methodName = request.getMethodName();
        Class<?>[] parameterTypes = request.getParameterTypes();
        Object[] parameters = request.getParameters();
        FastClass fastClass = FastClass.create(serviceClass);
        FastMethod fastMethod = fastClass.getMethod(methodName, parameterTypes);
        return fastMethod.invoke(serviceBean,parameters);

    }


}
